package com.xstudio.pvzreborn.data.provider;

import com.google.gson.JsonObject;
import com.xstudio.pvzreborn.PVZReborn;
import com.xstudio.pvzreborn.data.custom.ICustomRecipeProvider;
import com.xstudio.pvzreborn.mixin.MixinRecipeProvider;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DataProvider;
import net.minecraft.data.HashCache;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;

public abstract class PVZRecipeProvider implements DataProvider {

    protected final DataGenerator generator;

    public PVZRecipeProvider(DataGenerator generator) {
        this.generator = generator;
    }

    public static void saveAdvancement(HashCache cache, JsonObject advancementJson, Path path) {
        try {
            String s = MixinRecipeProvider.getGson().toJson(advancementJson);
            String s1 = SHA1.hashUnencodedChars(s).toString();
            if (!Objects.equals(cache.getHash(path), s1) || !Files.exists(path)) {
                Files.createDirectories(path.getParent());
                BufferedWriter bufferedwriter = Files.newBufferedWriter(path);

                try {
                    bufferedwriter.write(s);
                } catch (Throwable throwable1) {
                    if (bufferedwriter != null) {
                        try {
                            bufferedwriter.close();
                        } catch (Throwable throwable) {
                            throwable1.addSuppressed(throwable);
                        }
                    }

                    throw throwable1;
                }

                if (bufferedwriter != null) {
                    bufferedwriter.close();
                }
            }

            cache.putNew(path, s1);
        } catch (IOException ioexception) {
            PVZReborn.LOGGER.error("Couldn't save recipe advancement {}", path, ioexception);
        }

    }

    @Override
    public void run(@NotNull HashCache cache) {
        Path path = this.generator.getOutputFolder();
        Set<ResourceLocation> set = new HashSet<>();
        buildCraftingRecipes((recipe) -> {
            if (!set.add(recipe.getId())) {
                throw new IllegalStateException("Duplicate recipe " + recipe.getId());
            } else {
                StringBuilder otherPath = new StringBuilder("data/" + recipe.getId().getNamespace() + "/recipes/");
                if (this instanceof ICustomRecipeProvider customRecipeProvider) {
                    otherPath.append(customRecipeProvider.getFolderName()).append("/");
                }
                otherPath.append(recipe.getId().getPath()).append(".json");
                MixinRecipeProvider.saveRecipe(cache, recipe.serializeRecipe(), path.resolve(otherPath.toString()));
                JsonObject jsonobject = recipe.serializeAdvancement();
                if (jsonobject != null) {
                    saveAdvancement(cache, jsonobject, path.resolve("data/" + recipe.getId().getNamespace() + "/advancements/" + recipe.getAdvancementId().getPath() + ".json"));
                }
            }
        });
    }

    protected abstract void buildCraftingRecipes(Consumer<FinishedRecipe> consumer);

}
